;*******************************************************************************
;   CS/ECEn 124 Lab 3 - StopLight.asm: Software Toggle P1.0
;    Written by David Tanner
;    Started 5/3/2011
;   Finished 5/2/2011
;   MCLK = 14
;   CPI  = 1.33
;   MIPS = 11
;
;
;
;    Turn off the Watchdog.
;    Initialize the stack pointer to 0x0280 (SP).
;    Set Port 1 pin P1.0 (green LED) as output.
;    Turn on the green LED and delay 5 seconds.
;    Exclusive-OR the green LED with 0x01 and delay one second. Repeat 6 times.
;    Exclusive-OR the green LED with 0x01 and delay 1/5 second. Repeat 20 times.
;    Turn off the green LED and delay 10 seconds.
;    Repeat the stoplight cycle by jumping back to turning on the green LED.
;   
;
;
;    2 points    All software delays are implemented using a 1/10 second delay assembly subroutine.
;                The subroutine is implemented using a callee-save protocol.
;    2 points    The assembler directive .equ is used to define all delay counts and constants.
;    4 points    Your traffic stoplight machine works as specified. That is:
;                The green LED is on for 5 seconds.
;                The green LED blinks on and off at 1 second intervals for 6 seconds (3 offs and 3 ons).
;                Then the green LED blinks on and off at 0.2 second intervals for 4 seconds (10 offs and 10 ons).
;                And finally, the green LED is turned off for 10 seconds.
;    2 points    The total traffic light cycle time is 25 seconds with less than a 1/2 second error.
;
;    In addition to the above points, the following bonus/deductions apply:
;
;    1 point        Passed off with a TA at least one day early. (No timestamps please!)
;    1 point        The number of 1/10 second delays is passed to the timing subroutine on the stack.
;
;   Description: Toggle P1.0 on and off every 10 seconds.
;
;             MSP430F2013/F2274
;             -----------------
;         /|\|              XIN|-
;          | |                 |
;          --|RST          XOUT|-
;            |                 |
;            |             P1.0|-->GREEN LED
;
;*******************************************************************************
            .cdecls C,LIST, "msp430x20x3.h" ; MSP430F2013
delay       .equ    34858                   ; Set 1/10th of a second delay
green       .equ    50                      ; Green light is 5 seconds
yellowfl    .equ    10                      ; Yellow light is 1 second
yellowc     .equ    6                       ; flash yellow light 6 times
redfl       .equ    2                       ; Red light is 1/5 second
redc        .equ    20                      ; flash light 20 times
redoff      .equ    100                     ; turn off red light for 10 seconds
initpoint   .equ    0x0280                  ; Stack pointer constant
ledvalue    .equ    1                       ; Bit for the LED

;------------------------------------------------------------------------------
            .text                           ; beginning of executable code
;------------------------------------------------------------------------------


RESET:      mov.w   #initpoint,SP           ; init stack pointer, 5 cycles, 3 ins
            mov.w   #WDTPW+WDTHOLD,&WDTCTL  ; stop WDT, 5 cycles, 3 ins
            bis.b   #ledvalue,&P1DIR        ; set P1.0 as output, 4 cycles, 2 ins
            bic.b   #ledvalue,&P1OUT        ; turn off the light initially
            


mainloop:   push.w  #green                  ; Green Light Delay
            call    #single                 ; Green means Go!!!!

            push.w  #yellowfl               ; Yellow Flash Delay
            push.w  #yellowc                ; Yellow Flash Count
            call    #repeat                 ; Yellow, slow down

            push.w  #redfl                  ; Red Flash Delay
            push.w  #redc                   ; Red Flash Count
            call    #repeat                 ; Almost Red, better Stop!


            push.w  #redoff                 ; Red Light Delay
            call    #single                 ; Red means Stop!!!!

            jmp     mainloop

repeat:     pop.w   r4                      ; pop the stack pointer for where we go back to
            pop.w   r13                     ; flash count
            pop.w   r12                     ; We need to save the value, so we can push it again.
            push.w  r12                     ; put the value back on the stack to be used again

repeatloop: call    #xorlight               ; Flash the light and pause
            push.w  r12                     ; push the value onto the stack to be consumed by xorlight
            dec.w   r13                     ; Decrement by 1 Counter Loop
              jnz   repeatloop              ; Done n return to start loop
            pop.w   r12
            push    r4                      ; push the return location back onto the stack
            ret                             ; Return to whomever called us

single:     pop.w   r4                      ; pop the stack pointer for where we go back to
            call    #xorlight               ; turn the light on/off
            push.w  r4                      ; push the return location back onto the stack
            ret                             ; Return to whomever called us


xorlight:   pop.w   r5                      ; pop the stack pointer for where we go back to
            xor.b   #ledvalue,&P1OUT        ; toggle the led
            pop.w   r14                     ; get our Delay value

longloop:   push.w  #delay                  ; Push the delay counter for 1/10 second onto the stack
            call    #tenth                  ; Delay for 1/10th of a second
            dec.w   r14                     ; Decrement the loop for the Delay
              jnz   longloop                ; if we aren't done in the loop, go again
            push.w  r5                      ; push the return location back onto the stack
            ret                             ; Return to whomever called us


tenth:      pop.w   r6                      ; pop the stack pointer for where we go back to
            pop.w   r15                     ; get the delay count

shortloop:  dec.w   r15                     ; delay over? decrement by 1, 2 cycles , 2 ins
              jnz   shortloop               ; n repeat loop, 2 cycles, 1 ins
            push.w  r6                      ; push the return location back onto the stack
            ret                             ; Return to whomever called us




;------------------------------------------------------------------------------
;           Interrupt Vectors
;------------------------------------------------------------------------------
            .sect   ".reset"                ; MSP430 RESET Vector
            .short  RESET                   ; start address
            .end
